# gozerbot/eggs.py
#
#

""" 
    eggs related functions

    this module is used to load the eggs on which gozerbot depends from 
    specified dir .. most of the time this is the gozernest dir.

"""

__status__ = "seen"

## gozerbot imports

from utils.exception import handle_exception
from utils.log import rlog

## basic imports

import os
import sys

## defines

mainenv = None
latest = {}

## init function

def init(eggdir, log=False):
    """ make sure setuptools is available. """
    try: import setuptools
    except ImportError, ex:
        try:
            sys.path.insert(0, eggdir)
            for egg in os.listdir(eggdir):
                if egg.startswith('setuptools'):
                    log and rlog(10, 'eggs', 'loaded %s' % egg)
                    sys.path.insert(0, eggdir + os.sep + egg)
        except OSError: pass


## enable_egg function
    
def enable_egg(env, egg, log=True):

    """
        search for the latest version of an  egg in the enviroment and put 
        it on sys.path.

    """

    try:
        from pkg_resources import DistributionNotFound, VersionConflict, working_set, parse_requirements, require
        if not latest.has_key(egg.project_name): latest[egg.project_name] = egg
        req = egg.as_requirement()
        reqstr = str(req)
        reqq = parse_requirements([reqstr.replace('==', '>='), ])
        for e in working_set.resolve(reqq, mainenv):
            if e.location not in sys.path:
                env.add(e)
                working_set.add(e)
                working_set.add_entry(e.location)
                latest[egg.project_name] = e
                sys.path.insert(0, egg.location)
                log and rlog(3, 'eggs', 'loaded %s' % e)
            else: log and rlog(3, 'eggs', '%s already on path' % e)
    except DistributionNotFound, ex:
        env.add(egg)
        working_set.add(egg)
        working_set.add_entry(egg.location)
        latest[egg.project_name] = egg
        sys.path.insert(0, egg.location)
        log and rlog(3, 'eggs', 'loaded %s' % egg)
    except VersionConflict, ex:
        if egg > ex[0]:
            env.add(egg)
            working_set.add_entry(egg.location)
            working_set.add(egg)
            latest[egg.project_name] = egg
            sys.path.insert(0, egg.location)
            log and rlog(3, 'eggs', 'override %s' % egg)

## loadegg function

def loadegg(name, eggdirs=['gozernest',], log=True):
    """ scan eggdir for a egg matching `name`. """
    try:
        from pkg_resources import find_distributions, Environment
        global mainenv
        for eggdir in eggdirs:
            if mainenv: mainenv += Environment(eggdir)
            else: mainenv = Environment(eggdir)
            eggs = find_distributions(eggdir)
            for egg in eggs:
               if name.lower() in egg.project_name.lower(): enable_egg(mainenv, egg, log)
    except ImportError:  return
    except Exception, ex: handle_exception()

## loadeggs function

def loadeggs(eggdir, log=True):
    """ load all eggs in a directory. """
    rlog(3, 'eggs', 'scanning %s' % eggdir)
    try:
        from pkg_resources import find_distributions, Environment
        global mainenv
        if mainenv: mainenv += Environment(eggdir)
        else: mainenv = Environment(eggdir)
        eggs = find_distributions(eggdir)
        for egg in eggs:
            if not egg.project_name.startswith('setuptools'): enable_egg(mainenv, egg, log)
    except ImportError: return
    except Exception, ex: handle_exception()
    res = []
    for name, egg in latest.iteritems(): res.append("%s: %s" % (name, egg.version))
    rlog(3, 'eggs', 'loaded: %s' % ' .. '.join(res))

## initialisation

init(os.getcwd())
init(os.getcwd() + os.sep + 'gozernest')
